#pragma once
#include <iostream>
#include <jsoncpp/json/json.h>
#include <string>
#include<memory>
namespace Protocal
{
    // 我们规定报文为：长度+分隔符+内容+分隔符
    const std::string ProtSep = " ";
    const std::string LineBreakSep = "\r\n";
    std::string Encode(const std::string &msg)
    {
        std::string len = std::to_string(msg.size());
        std::string package = len + LineBreakSep + msg + LineBreakSep;
        return package;
    }
    bool Decode(std::string &package, std::string *msg)
    {
        int pos = package.find(LineBreakSep);
        if (pos == std::string::npos)
            return pos;
        std::string lens = package.substr(0, pos);
        int msglen = std::stoi(lens);
        int total = msglen + lens.size() + 2 * LineBreakSep.size();
        if (package.size() < total)
            return false;
        *msg = package.substr(pos + LineBreakSep.size(), msglen);
        package.erase(0, total);
        return true;
    }
    class Request
    {
    public:
        Request() {}
        Request(int data_x, int data_y, char oper) : _data_x(data_x), _data_y(data_y), _oper(oper) {}
        void Debug()
        {
            std::cout << "第一个参数为:" << _data_x << std::endl;
            std::cout << "第二个参数为:" << _data_y << std::endl;
            std::cout << "操作符为:" << _oper << std::endl;
        }
        bool Serialize(std::string *out)
        {
            Json::Value root;
            root["data_x"] = _data_x; // 将反序列化好的数据存入Json
            root["data_y"] = _data_y;
            root["oper"] = _oper;
            Json::FastWriter writer; // 使用writer将Json中的数据按照字符串形式写出，即序列化
            *out = writer.write(root);
            return true;
        }
        bool DeSerialize(std::string &in)
        {
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root); // 使用reader将序列化好的数据进行反序列化得到Json
            if (res)
            {
                _data_x = root["data_x"].asInt();
                _data_y = root["data_y"].asInt();
                _oper = root["oper"].asInt();
            }
            return res;
        }

        int GetX()
        {
            return _data_x;
        }
        int GetY()
        {
            return _data_y;
        }
        char GetOper()
        {
            return _oper;
        }

    private:
        int _data_x; // 第一个参数
        int _data_y; // 第二个参数
        char _oper;  // 操作符
    };

    class Response
    {
    public:
        Response() {}
        Response(int result, int code) : _result(result), _code(code) {}
        bool Serialize(std::string *out)
        {
            Json::Value root;
            root["result"] = _result;
            root["code"] = _code;
            Json::FastWriter writer;
            *out = writer.write(root);
            return true;
        }
        bool DeSerialize(std::string &in)
        {
            Json::Value root;
            Json::Reader reader;
            bool res = reader.parse(in, root);
            if (res)
            {
                _result = root["result"].asInt();
                _code = root["code"].asInt();
            }
            return res;
        }
        void SetResult(int res) { _result = res; }
        void SetCode(int code) { _code = code; }
        int GetResult() { return _result; }
        int GetCode() { return _code; }

    private:
        int _result; // 结果
        int _code;   // 状态
    };

    //简单的工厂类模式，建造者模式
    class Factor
    {
        public:
        std::shared_ptr<Request> BuildRequest()
        {
            std::shared_ptr<Request> req=std::make_shared<Request>();
            return req;
        }
        std::shared_ptr<Request> BuildRequest(int x,int y,int oper)
        {
            std::shared_ptr<Request> req=std::make_shared<Request>(x,y,oper);
            return req;
        }
        std::shared_ptr<Response> BuildResponse()
        {
            std::shared_ptr<Response> req=std::make_shared<Response>();
            return req;
        }
        std::shared_ptr<Response> BuildResponse(int result,int code)
        {
            std::shared_ptr<Response> req=std::make_shared<Response>(result,code);
            return req;
        }
    };

}